sam build で容量の大きなファイルや大量のファイルをプロジェクトルートに配置した場合に Setting DockerBuildArgs で時間がかかる際の対処方法
困っていた内容
Lambda向けのコンテナイメージ を AWS SAM を利用してデプロイしようとしておりますが、比較的コード量の少ない Dockerfile でも、sam build に数分の実行時間がかかります。 そのため、ビルド時間を短縮する方法をご教示ください。
なお、ローカルマシンには、以下のようなディレクトリ構造でプロジェクトのルートディレクトリに容量の大きいファイルや大量のファイルがあります。
$ tree . ├── README.md ├── __init__.py ├── events │ └── event.json ├── foo_1.txt | -- 誌面の都合上、省略。実際は、大量のファイルがある -- | ├── foo_XX.txt ├── hello_world │ ├── Dockerfile │ ├── __init__.py │ ├── app.py │ └── requirements.txt ├── template.yaml └── tests ├── __init__.py └── unit ├── __init__.py └── test_handler.py
以下が、sam build を実行した際のコマンドの結果です。
「2022-04-08 17:33:37,063 | Setting DockerBuildArgs: {} for HelloWorldFunction function」の箇所で時間がかかってしまいます。
$ sam build --debug 2022-04-08 17:33:36,538 | Telemetry endpoint configured to be https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics --- 省略 --- 2022-04-08 17:33:37,055 | Building codeuri: /Users/**************/docker/nakano-sam-test runtime: None metadata: {'Dockerfile': 'Dockerfile', 'DockerContext': '/Users/**************/docker/nakano-sam-test/hello_world', 'DockerTag': 'python3.9-v1'} architecture: x86_64 functions: ['HelloWorldFunction'] 2022-04-08 17:33:37,055 | Building to following folder /Users/**************/docker/nakano-sam-test/.aws-sam/build/HelloWorldFunction 2022-04-08 17:33:37,055 | Building image for HelloWorldFunction function 2022-04-08 17:33:37,063 | Setting DockerBuildArgs: {} for HelloWorldFunction function Step 1/4 : FROM public.ecr.aws/lambda/python:3.9 3.9: Pulling from lambda/python e6842361273f: Already exists 0a074f8b3d7a: Pull complete df68587c4258: Pull complete 1418415b0a5d: Pull complete f2796bda02b6: Pull complete 8c16de5f53b2: Pull complete Status: Downloaded newer image for public.ecr.aws/lambda/python:3.9 ---> 2df2e3c405fe Step 2/4 : COPY app.py requirements.txt ./ ---> ef3029fffcba Step 3/4 : RUN python3.9 -m pip install -r requirements.txt -t . ---> Running in 3bf7eae77c13 Collecting requests Downloading requests-2.27.1-py2.py3-none-any.whl (63 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 63.1/63.1 KB 991.8 kB/s eta 0:00:00 Collecting charset-normalizer~=2.0.0 Downloading charset_normalizer-2.0.12-py3-none-any.whl (39 kB) Collecting idna=2.5 Downloading idna-3.3-py3-none-any.whl (61 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 61.2/61.2 KB 2.5 MB/s eta 0:00:00 Collecting certifi>=2017.4.17 Downloading certifi-2021.10.8-py2.py3-none-any.whl (149 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 149.2/149.2 KB 1.8 MB/s eta 0:00:00 Collecting urllib3=1.21.1 Downloading urllib3-1.26.9-py2.py3-none-any.whl (138 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 139.0/139.0 KB 2.1 MB/s eta 0:00:00 Installing collected packages: certifi, urllib3, idna, charset-normalizer, requests Successfully installed certifi-2021.10.8 charset-normalizer-2.0.12 idna-3.3 requests-2.27.1 urllib3-1.26.9 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv ---> c93dfe84bd5e Step 4/4 : CMD ["app.lambda_handler"] ---> Running in 737adb584ca4 ---> c93bd4799df1 Successfully built c93bd4799df1 Successfully tagged helloworldfunction:python3.9-v1 2022-04-08 17:34:00,912 | No Parameters detected in the template 2022-04-08 17:34:00,927 | There is no customer defined id or cdk path defined for resource HelloWorldFunction, so we will use the resource logical id as the resource id 2022-04-08 17:34:00,927 | There is no customer defined id or cdk path defined for resource ServerlessRestApi, so we will use the resource logical id as the resource id 2022-04-08 17:34:00,928 | There is no customer defined id or cdk path defined for resource HelloWorldFunction, so we will use the resource logical id as the resource id Build Succeeded
どう対応すればいいの?
.dockerignore
にコンテナイメージのビルドに必須ではないファイルを含めないよう記載ください。
どういう動作なの?
sam build が遅い原因としては、コンテナイメージのビルド時に Docker Daemon へのビルドコンテキストの送信に時間がかかっていることが原因です。
Docker でコンテナイメージのビルドを行う際、ビルド対象のディレクトリ配下のファイルが「ビルドコンテキスト」として Docker Daemon へ送信され、Docker Daemon にてコンテナイメージのビルドが行われるという動作になります。
また、ビルドコンテキスト送信の際、ビルド対象ディレクトリ配下に大量のファイルやサイズの大きいファイルが含まれていると、送信に時間がかかリます。
解決方法
以下の例のように、.dockerignore
をプロジェクトのルートディレクトリに配置します。
ビルドに不要なファイルである foo_XXX.txt のファイルを Docker Daemon へ送信されないように追記します。
$ vim .dockerignore foo* # こちらを、追記
再度、ビルドを実行すると、Setting DockerBuildArgs の箇所が高速化されるか確認します。
$ sam build --debug 2022-04-08 17:38:53,278 | Telemetry endpoint configured to be https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics --- 省略 --- 2022-04-08 17:38:53,915 | Building codeuri: /Users/****************/docker/nakano-sam-test runtime: None metadata: {'Dockerfile': 'Dockerfile', 'DockerContext': '/Users/****************/docker/nakano-sam-test/hello_world', 'DockerTag': 'python3.9-v1'} architecture: x86_64 functions: ['HelloWorldFunction'] 2022-04-08 17:38:53,916 | Building to following folder /Users/****************/docker/nakano-sam-test/.aws-sam/build/HelloWorldFunction 2022-04-08 17:38:53,916 | Building image for HelloWorldFunction function 2022-04-08 17:38:53,921 | Setting DockerBuildArgs: {} for HelloWorldFunction function Step 1/4 : FROM public.ecr.aws/lambda/python:3.9 ---> 2df2e3c405fe Step 2/4 : COPY app.py requirements.txt ./ ---> Using cache ---> ef3029fffcba Step 3/4 : RUN python3.9 -m pip install -r requirements.txt -t . ---> Using cache ---> c93dfe84bd5e Step 4/4 : CMD ["app.lambda_handler"] ---> Using cache ---> c93bd4799df1 Successfully built c93bd4799df1 Successfully tagged helloworldfunction:python3.9-v1 2022-04-08 17:38:54,246 | No Parameters detected in the template 2022-04-08 17:38:54,260 | There is no customer defined id or cdk path defined for resource HelloWorldFunction, so we will use the resource logical id as the resource id 2022-04-08 17:38:54,261 | There is no customer defined id or cdk path defined for resource ServerlessRestApi, so we will use the resource logical id as the resource id 2022-04-08 17:38:54,261 | There is no customer defined id or cdk path defined for resource HelloWorldFunction, so we will use the resource logical id as the resource id Build Succeeded
上記の例では、30 秒ほどかかっていたビルド時間が 1 秒程度に短縮されました。